import datetime
import os

import jwt
from fastapi import Security, HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from passlib.context import CryptContext
from starlette.status import HTTP_401_UNAUTHORIZED


class AuthHandler:
    security = HTTPBearer()
    pad_context = CryptContext(schemes=['bcrypt'])
    secret = os.environ.get('SECRET_KEY')

    def get_password_hash(self, password):
        return self.pad_context.hash(password)

    def verify_password(self, password, hashed_password):
        return self.pad_context.verify(password, hashed_password)

    def encode_token(self, username: str):
        payload = {
            'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=8),
            'iat': datetime.datetime.utcnow(),
            'sub': username
        }
        return jwt.encode(payload, self.secret, algorithm='HS256')

    def decode_token(self, token):
        try:
            payload = jwt.decode(token, self.secret, algorithms=['HS256'])
            return payload['sub']
        except jwt.ExpiredSignatureError:
            raise HTTPException(status_code=401, detail='Token expired')
        except jwt.InvalidTokenError:
            raise HTTPException(status_code=401, detail='Invalid token')

    def auth_wrapper(self, auth: HTTPAuthorizationCredentials = Security(security)):
        return self.decode_token(auth.credentials)

    # 可以基于下面的这个定义一个依赖项注入读取对应的用户信息
    async def get_current_user(self, auth: HTTPAuthorizationCredentials = Security(security), *args, **kwargs):
        # 解析错误的时候的抛出的自动异常
        credential_exception = HTTPException(status_code=HTTP_401_UNAUTHORIZED, detail='Could not validate credentials')
        username = self.decode_token(auth.credentials)
        if username is None:
            raise credential_exception
        else:
            pass
